package com.oa.store.service.oa.leave.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.oa.store.manager.oa.leave.LeaveManager;
import com.oa.store.model.oa.Leave;
import com.oa.store.service.oa.leave.LeaveWorkflowService;
import com.oa.store.util.Page;

@Service("workflowService")
@Transactional(readOnly = true)
public class LeaveWorkflowServiceImpl implements LeaveWorkflowService{

	private static Logger logger = LoggerFactory.getLogger(LeaveWorkflowServiceImpl.class);
	
	@Autowired
	private LeaveManager leaveManager;
	
	@Autowired
	private IdentityService identityService;
	
	@Autowired
	private RuntimeService runtimeService;
	
	@Autowired
	private TaskService taskService;
	
	@Autowired
	private RepositoryService repositoryService;
	
	@Transactional(readOnly = false)
	public ProcessInstance startWorkflow(Leave entity,Map<String, Object> variables) {
		leaveManager.insertLeave(entity);
		logger.debug("save entity:{}",entity);
		String businessKey = entity.getId().toString();
		ProcessInstance processInstance = null;
		try {
			identityService.setAuthenticatedUserId(entity.getUserId());
	 		processInstance = runtimeService.startProcessInstanceByKey("leave",businessKey,variables);
	 		String processInstanceId = processInstance.getId();
			entity.setProcessInstanceId(processInstanceId);
			logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"leave", businessKey, processInstanceId, variables});
	    } finally {
	        identityService.setAuthenticatedUserId(null);
	    }
		return processInstance;
	}

	public List<Leave> findTodoTasks(String userId, Page<Leave> page, int[] pageParams) {
		List<Leave> results = new ArrayList<Leave>();
        List<Task> tasks = new ArrayList<Task>();

        // 根据当前人的ID查询
        TaskQuery todoQuery = taskService.createTaskQuery().processDefinitionKey("leave").taskAssignee(userId).active().orderByTaskId().desc()
                .orderByTaskCreateTime().desc();
        List<Task> todoList = todoQuery.listPage(pageParams[0], pageParams[1]);

        // 根据当前人未签收的任务
        TaskQuery claimQuery = taskService.createTaskQuery().processDefinitionKey("leave").taskCandidateUser(userId).active().orderByTaskId().desc()
                .orderByTaskCreateTime().desc();
        List<Task> unsignedTasks = claimQuery.listPage(pageParams[0], pageParams[1]);

        // 合并
        tasks.addAll(todoList);
        tasks.addAll(unsignedTasks);

        // 根据流程的业务ID查询实体并关联
        for (Task task : tasks) {
            String processInstanceId = task.getProcessInstanceId();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
            String businessKey = processInstance.getBusinessKey();
            if (businessKey == null) {
                continue;
            }
            Leave leave = leaveManager.getLeave(new Long(businessKey));
            leave.setTask(task);
            leave.setProcessInstance(processInstance);
            leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
            results.add(leave);
        }
        page.setTotalCount(todoQuery.count() + claimQuery.count());
        page.setResult(results);
        return results;
	}
	
	/**
     * 查询流程定义对象
     *
     * @param processDefinitionId 流程定义ID
     * @return
     */
    protected ProcessDefinition getProcessDefinition(String processDefinitionId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        return processDefinition;
    }

}
